package com.gjy.aop;

import com.gjy.comment.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.junit.jupiter.api.Order;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * 菜单权限
 *
 * @author 宫静雨
 * @version 1.0
 * @since 2023-02-03 15:26:28
 */
@Slf4j
@Component
@Order(1)
@Aspect
public class AuthPermissionAspect {

    /**
     * 用于获取方法参数定义名字.
     */
    private final DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
    /**
     * 用于SpEL表达式解析.
     */
    private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();

    @Around("@annotation(authPermission)")
    public Object beforeMethod(ProceedingJoinPoint joinPoint,
                               AuthPermission authPermission) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取登录用户token
        String loginToken = getValBySpEl(authPermission.loginToken(), methodSignature, joinPoint.getArgs());
        if (!StringUtils.hasText(loginToken)) {
            return AjaxResult.error("当前登录状态无效，请登录后再进行操作");
        }
        //查询是否拥有该项操作权限
        /*String hasAuth = authMenuMapper.checkUserHasPerms(loginToken, authPermissionAnnotations.operatePerms());
        if (!BooleanEnum.TRUE.getValue().equals(hasAuth)) {
            return AjaxResult.error("您无此操作权限！");
        }*/
        //校验通过，执行正常流程
        log.info("loginToken = {}, operatePerms = {}", loginToken, authPermission.operatePerms());
        return joinPoint.proceed();
    }


    /**
     * 解析spEL表达式
     *
     * @param spEl            spel表达式
     * @param methodSignature methodSignature
     * @param args            args
     * @return string
     */
    private String getValBySpEl(String spEl, MethodSignature methodSignature, Object[] args) {
        //获取方法形参名数组
        String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod());
        if (paramNames != null && paramNames.length > 0) {
            Expression expression = spelExpressionParser.parseExpression(spEl);
            // spring的表达式上下文对象
            EvaluationContext context = new StandardEvaluationContext();
            // 给上下文赋值
            for (int i = 0; i < args.length; i++) {
                //设置变量
                context.setVariable(paramNames[i], args[i]);
            }
            return Objects.requireNonNull(expression.getValue(context)).toString();
        }
        return null;
    }

}
